home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 1.toast / pc / sample code / contributed / waste / waste 1.3 / source / weinlineinput.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  18.3 KB  |  786 lines

  1. /*
  2.  *    WEInlineInput.c
  3.  *
  4.  *    WASTE PROJECT
  5.  *  Inline Input Support
  6.  *
  7.  *  Copyright (c) 1993-1998 Marco Piovanelli
  8.  *    All Rights Reserved
  9.  *
  10.  *  C port by Dan Crevier
  11.  *
  12.  */
  13.  
  14.  
  15. #include "WASTEIntf.h"
  16.  
  17. // special event ID used by Kotoeri and other input methods
  18.  
  19. enum
  20. {
  21.     kGetText = 'gtxt'
  22. };
  23.  
  24. #if WASTE_TSM_SUPPORT
  25.  
  26. // static variables
  27.  
  28. static AEEventHandlerUPP _weUpdateActiveInputAreaHandler = nil;
  29. static AEEventHandlerUPP _wePositionToOffsetHandler = nil;
  30. static AEEventHandlerUPP _weOffsetToPositionHandler = nil;
  31. static AEEventHandlerUPP _weGetTextHandler = nil;
  32.  
  33. pascal OSErr _WEHiliteRangeArray(TextRangeArrayHandle hTray, WEHandle hWE)
  34. {
  35.     WEPtr pWE = *hWE;    // assume WE record is already locked
  36.     TextRangePtr pRange;
  37.     SInt32 rangeStart, rangeEnd;
  38.     SInt16 hiliteStyle;
  39.     WETextStyle ts;
  40.     SInt16 rangeIndex;
  41.     Boolean saveTrayLock;
  42.     OSErr err;
  43.  
  44.     // lock down the range array
  45.     saveTrayLock = _WESetHandleLock((Handle)hTray, true);
  46.     pRange = (*hTray)->fRange;
  47.  
  48.     // walk the hilite range array
  49.     for (rangeIndex = (*hTray)->fNumOfRanges - 1; rangeIndex >= 0; rangeIndex-- )
  50.     {
  51.  
  52.         // the offsets in the range array are relative to the beginning
  53.         // of the active input area: convert them to absolute offsets
  54.         rangeStart = pWE->tsmAreaStart + pRange->fStart;
  55.         rangeEnd = pWE->tsmAreaStart + pRange->fEnd;
  56.         hiliteStyle = pRange->fHiliteStyle;
  57.  
  58.         // take the absolute value of hiliteStyle
  59.         hiliteStyle = ABS(hiliteStyle);
  60.  
  61.         // if hiliteStyle is kCaretPosition, set the selection range
  62.         if (hiliteStyle == kCaretPosition)
  63.         {
  64.             pWE->selStart = rangeStart;
  65.             pWE->selEnd = rangeEnd;
  66.         }
  67.         else
  68.         {
  69.             hiliteStyle -= kRawText;
  70.             // otherwise set the WETextStyle flags of the specified range appropriately
  71.             if ((hiliteStyle >= 0) && (hiliteStyle <= 3))
  72.             {
  73.                 ts.tsFlags = 0x10 + (hiliteStyle << tsTSMSelected);
  74.                 if ((err = _WESetStyleRange(rangeStart, rangeEnd, weDoFlags, &ts, hWE)) != noErr)
  75.                 {
  76.                     goto cleanup;
  77.                 }
  78.             }
  79.         }
  80.         // go to next text range element
  81.         pRange++;
  82.     }
  83.  
  84.     // clear result code
  85.     err = noErr;
  86.  
  87. cleanup:
  88.     // unlock the range array
  89.     _WESetHandleLock((Handle)hTray, saveTrayLock);
  90.  
  91.     return err;
  92. }
  93.  
  94. static pascal OSErr _WEHandleUpdateActiveInputArea(const AppleEvent *ae, AppleEvent *reply, SInt32 handlerRefCon)
  95. {
  96. #pragma unused(reply, handlerRefCon)
  97.     WEHandle hWE = nil;
  98.     WEPtr pWE;
  99.     AEDesc text;
  100.     AEDesc hiliteTray;
  101.     TextRange pinRange;
  102.     SInt32 totalLength;
  103.     SInt32 fixLength;
  104.     SInt32 tsmOffset;
  105.     DescType actualType;
  106.     SInt32 actualSize;
  107.     GrafPtr savePort;
  108.     WEActionHandle hAction;
  109.     Boolean saveAutoScroll;
  110.     Boolean saveTextLock;
  111.     Boolean saveWELock = false;
  112.     OSErr err;
  113.  
  114.     // initialize descriptors to null values
  115.     text.descriptorType = typeNull;
  116.     text.dataHandle = nil;
  117.     hiliteTray.descriptorType = typeNull;
  118.     hiliteTray.dataHandle = nil;
  119.  
  120.     // extract WE handle
  121.     if ((err = AEGetParamPtr(ae, keyAETSMDocumentRefcon, typeLongInteger,
  122.             &actualType, &hWE, sizeof(hWE), &actualSize)) != noErr)
  123.     {
  124.         goto cleanup;
  125.     }
  126.  
  127.     // lock the WE handle
  128.     saveWELock = _WESetHandleLock((Handle) hWE, true);
  129.     pWE = *hWE;
  130.  
  131.     // return an error code if this instance is read-only
  132.     err = weReadOnlyErr;
  133.     if (BTST(pWE->features, weFReadOnly))
  134.     {
  135.         goto cleanup;
  136.     }
  137.  
  138.     // call the pre-update callback, if present
  139.     if (pWE->tsmPreUpdate != nil)
  140.     {
  141.         CallWETSMPreUpdateProc(hWE, pWE->tsmPreUpdate);
  142.     }
  143.  
  144.     // hide the caret if it's showing
  145.     if (BTST(pWE->flags, weFCaretVisible))
  146.     {
  147.         _WEBlinkCaret(hWE);
  148.     }
  149.  
  150.     // extract the text descriptor
  151.     if ((err = AEGetParamDesc(ae, keyAETheData, typeChar, &text)) != noErr)
  152.     {
  153.         goto cleanup;
  154.     }
  155.  
  156.     // get total length of text in the active input area
  157.     totalLength = GetHandleSize(text.dataHandle);
  158.  
  159.     // extract the length of confirmed text in the active input area
  160.     if ((err = AEGetParamPtr(ae, keyAEFixLength, typeLongInteger, &actualType,
  161.             &fixLength, sizeof(fixLength), &actualSize)) != noErr)
  162.     {
  163.         goto cleanup;
  164.     }
  165.  
  166.     // if fixLength = -1, all text is confirmed
  167.     if (fixLength == -1)
  168.     {
  169.         fixLength = totalLength;
  170.     }
  171.  
  172.     // if there's currently no active input area, open one
  173.     if (pWE->tsmAreaStart == kInvalidOffset)
  174.     {
  175.         pWE->tsmAreaStart = pWE->selStart;
  176.         pWE->tsmAreaEnd = pWE->selEnd;
  177.  
  178.         // are we tracking a typing sequence?
  179.         if (!WEIsTyping(hWE))
  180.         {
  181.             // nope; so start a new one
  182.             // increment modification count
  183.             pWE->modCount++;
  184.  
  185.             // if undo support is enabled, the inline session just started may initiate
  186.             if (BTST(pWE->features, weFUndoSupport))
  187.             {
  188.                 WEClearUndo(hWE);
  189.                 if (_WENewAction(pWE->selStart, pWE->selEnd, 0, weAKTyping, 0, hWE, &hAction) == noErr)
  190.                 {
  191.                     _WEPushAction(hAction);
  192.                 }
  193.             }
  194.         }
  195.     }
  196.  
  197.     tsmOffset = pWE->tsmAreaStart;
  198.  
  199.     // the new text replaces whatever is in the active input area
  200.     if ((err = _WEDeleteRange(tsmOffset, pWE->tsmAreaEnd, hWE)) != noErr)
  201.     {
  202.         goto cleanup;
  203.     }
  204.  
  205.     // synchronize the null style, so font script matches the keyboard script
  206.     _WESynchNullStyle(hWE);
  207.  
  208.     // set the port font for good measure
  209.     GetPort(&savePort);
  210.     SetPort(pWE->port);
  211.     TextFont(pWE->nullStyle.runStyle.tsFont);
  212.     SetPort(savePort);
  213.  
  214.     // insert the text
  215.     saveTextLock = _WESetHandleLock(text.dataHandle, true);
  216.     err = _WEInsertText(tsmOffset, *(text.dataHandle), totalLength, hWE);
  217.     _WESetHandleLock(text.dataHandle, saveTextLock);
  218.     if (err != noErr)
  219.     {
  220.         goto cleanup;
  221.     }
  222.  
  223.     // extract pin range
  224.     if ((err = AEGetParamPtr(ae, keyAEPinRange, typeTextRange, &actualType,
  225.             &pinRange, sizeof(pinRange), &actualSize)) == noErr)
  226.     {
  227.         // we want absolute offsets
  228.         pinRange.fStart += tsmOffset;
  229.         pinRange.fEnd += tsmOffset;
  230.     }
  231.     else
  232.     {
  233.         // a missing pin range descriptor isn't an error; everything else is
  234.         if (err != errAEDescNotFound)
  235.         {
  236.             goto cleanup;
  237.         }
  238.  
  239.         // default pin range is active input area
  240.         pinRange.fStart = tsmOffset;
  241.         pinRange.fEnd = pWE->tsmAreaEnd;
  242.     }
  243.  
  244.     // NOTE: if fixLength == totalLength, the inline input session is over, so, in theory,
  245.     // hiliteTray should either be missing or not specify any range to be underlined.
  246.     // Unfortunately, some input methods (like Apple's input method for Simplified Chinese)
  247.     // do specify kConvertedText (= thin black underline) for the whole text when
  248.     // the text is confirmed (is this a bug?).  To work around this, we deliberately ignore
  249.     // the hiliteTray parameter when fixLength = totalLength.
  250.  
  251.     if (fixLength != totalLength)
  252.     {
  253.         pWE->tsmAreaStart += fixLength;  // added by Kiyoshi Gomasaki for ATOK compatibility
  254.  
  255.         // extract the highlight range array
  256.         if ((err = AEGetParamDesc(ae, keyAEHiliteRange, typeTextRangeArray, &hiliteTray)) != noErr)
  257.         {
  258.             if (err != errAEDescNotFound)
  259.             {
  260.                 goto cleanup;
  261.             }
  262.         }
  263.     }
  264.  
  265.     if (hiliteTray.dataHandle != nil)
  266.     {
  267.         if ((err = _WEHiliteRangeArray((TextRangeArrayHandle) hiliteTray.dataHandle, hWE)) != noErr)
  268.         {
  269.             goto cleanup;
  270.         }
  271.     }
  272.     else
  273.     {
  274.         pWE->selStart = tsmOffset + fixLength;
  275.         pWE->selEnd = pWE->selStart;
  276.     }
  277.  
  278.     // temporarily disable auto-scroll, as we need to scroll manually according to pinRange
  279.     saveAutoScroll = BTST(pWE->features, weFAutoScroll) ? true : false;
  280.     BCLR(pWE->features, weFAutoScroll);
  281.  
  282.     // redraw the active input area
  283.     if ((err = _WERedraw(tsmOffset, tsmOffset + totalLength, hWE)) != noErr)
  284.     {
  285.         goto cleanup;
  286.     }
  287.  
  288.     if (saveAutoScroll)
  289.     {
  290.  
  291.         // re-enable auto-scroll
  292.         BSET(pWE->features, weFAutoScroll);
  293.  
  294.         // scroll the pin range into view
  295.         if (!_WEScrollIntoView(pinRange.fStart, hWE))
  296.         {
  297.             if (pinRange.fStart != pinRange.fEnd)
  298.             {
  299.                 _WEScrollIntoView(pinRange.fEnd, hWE);
  300.             }
  301.         }
  302.     }
  303.  
  304.     // update the boundaries of the active input area
  305.     // if fixLength = totalLength, the inline input session is over: close the active input area
  306.     if (fixLength == totalLength)
  307.     {
  308.         pWE->tsmAreaStart = kInvalidOffset;
  309.         pWE->tsmAreaEnd = kInvalidOffset;
  310.  
  311.         // adjust undo buffer (if any) for the confirmed text
  312.         _WEAdjustUndoRange(fixLength, hWE);
  313.     }
  314.     else
  315.     {
  316.         // otherwise, fixLength defines the boundaries of the active input area
  317.         pWE->tsmAreaStart = tsmOffset + fixLength;
  318.         pWE->tsmAreaEnd = tsmOffset + totalLength;
  319.     }
  320.  
  321.     // call the post-update callback, if present
  322.     if (pWE->tsmPostUpdate != nil)
  323.     {
  324.         CallWETSMPostUpdateProc(hWE, fixLength, pWE->tsmAreaStart, pWE->tsmAreaEnd,
  325.             pinRange.fStart, pinRange.fEnd, pWE->tsmPostUpdate);
  326.     }
  327.  
  328.     // clear result code
  329.     err = noErr;
  330.  
  331. cleanup:
  332.     // clean up
  333.     AEDisposeDesc(&text);
  334.     AEDisposeDesc(&hiliteTray);
  335.  
  336.     // unlock the WE record
  337.     if (hWE !=nil)
  338.     {
  339.         _WESetHandleLock((Handle) hWE, saveWELock);
  340.     }
  341.  
  342.     // return result code
  343.     return err;
  344. }
  345.  
  346. static pascal OSErr _WEHandlePositionToOffset(const AppleEvent *ae, AppleEvent *reply, SInt32 handlerRefCon)
  347. {
  348. #pragma unused(handlerRefCon)
  349.     WEHandle hWE = nil;
  350.     WEPtr pWE;
  351.     Point position;
  352.     LongPt thePoint;
  353.     SInt16 regionClass;
  354.     SInt32 offset;
  355.     DescType actualType;
  356.     SInt32 actualSize;
  357.     GrafPtr savePort;
  358.     WEEdge edge;
  359.     Boolean saveWELock = false;
  360.     OSErr err;
  361.  
  362.     // extract WE handle
  363.     if ((err = AEGetParamPtr(ae, keyAETSMDocumentRefcon, typeLongInteger,
  364.             &actualType, &hWE, sizeof(hWE), &actualSize)) != noErr)
  365.     {
  366.         goto cleanup;
  367.     }
  368.  
  369.     // lock the WE record
  370.     saveWELock = _WESetHandleLock((Handle) hWE, true);
  371.     pWE = *hWE;
  372.  
  373.     // extract position parameter
  374.     if ((err = AEGetParamPtr(ae, keyAECurrentPoint, typeQDPoint, &actualType, &position, sizeof(position), &actualSize)) != noErr)
  375.     {
  376.             goto cleanup;
  377.     }
  378.  
  379.     // convert position to local...
  380.     GetPort(&savePort);
  381.     SetPort(pWE->port);
  382.     GlobalToLocal(&position);
  383.     SetPort(savePort);
  384.  
  385.     // ...and long coordinates
  386.     WEPointToLongPoint(position, &thePoint);
  387.  
  388.     // find the byte offset and the edge value corresponding to the given position
  389.     offset = WEGetOffset(&thePoint, &edge, hWE);
  390.  
  391.     // determine the region class
  392.     if (WELongPointInLongRect(&thePoint, &pWE->viewRect))
  393.     {
  394.         if (_WEOffsetInRange(offset, edge, pWE->tsmAreaStart, pWE->tsmAreaEnd))
  395.         {
  396.               regionClass = kTSMInsideOfActiveInputArea;
  397.             // if the given position is within the active input area, we're supposed to return
  398.             // an offset relative to the beginning of this area (thanks, Martin!)
  399.             offset -= pWE->tsmAreaStart;
  400.         }
  401.         else
  402.         {
  403.             // otherwise the offset is relative to the beginning of the body
  404.             regionClass = kTSMInsideOfBody;
  405.         }
  406.     }
  407.     else
  408.     {
  409.         regionClass = kTSMOutsideOfBody;
  410.     }
  411.  
  412.     // add region class parameter to reply
  413.     if ((err = AEPutParamPtr(reply, keyAERegionClass, typeShortInteger, ®ionClass, sizeof(regionClass))) != noErr)
  414.     {
  415.         goto cleanup;
  416.     }
  417.  
  418.     // add offset parameter to reply
  419.     if ((err = AEPutParamPtr(reply, keyAEOffset, typeLongInteger, &offset, sizeof(offset))) != noErr)
  420.     {
  421.         goto cleanup;
  422.     }
  423.  
  424.     // add edge parameter to reply
  425.     if ((err = AEPutParamPtr(reply, keyAELeftSide, typeBoolean, &edge, sizeof(edge))) != noErr)
  426.     {
  427.         goto cleanup;
  428.     }
  429.  
  430.     // clear result code
  431.     err = noErr;
  432.  
  433. cleanup:
  434.     // unlock the WE record
  435.     if (hWE != nil)
  436.     {
  437.         _WESetHandleLock((Handle) hWE, saveWELock);
  438.     }
  439.  
  440.     // return result code
  441.     return err;
  442. }
  443.  
  444. static pascal OSErr _WEHandleOffsetToPosition(const AppleEvent *ae, AppleEvent *reply, SInt32 handlerRefCon)
  445. {
  446. #pragma unused(handlerRefCon)
  447.     WEHandle hWE = nil;
  448.     WEPtr pWE;
  449.     SInt32 offset;
  450.     LongPt thePoint;
  451.     Point position;
  452.     SInt16 lineHeight;
  453.     DescType actualType;
  454.     SInt32 actualSize;
  455.     GrafPtr savePort;
  456.     Boolean saveWELock = false;
  457.     OSErr err;
  458.  
  459.     // extract WE handle
  460.     if ((err = AEGetParamPtr(ae, keyAETSMDocumentRefcon, typeLongInteger,
  461.             &actualType, &hWE, sizeof(hWE), &actualSize)) != noErr)
  462.     {
  463.         goto cleanup;
  464.     }
  465.  
  466.     // lock the WE record
  467.     saveWELock = _WESetHandleLock((Handle) hWE, true);
  468.     pWE = *hWE;
  469.  
  470.     // if there's no active input area, return errOffsetInvalid
  471.     err = errOffsetInvalid;
  472.     if (pWE->tsmAreaStart < 0)
  473.     {
  474.         goto cleanup;
  475.     }
  476.  
  477.     // extract the offset parameter
  478.     if ((err = AEGetParamPtr(ae, keyAEOffset, typeLongInteger, &actualType, &offset, sizeof(offset), &actualSize)) != noErr)
  479.     {
  480.         goto cleanup;
  481.     }
  482.  
  483.     // offset is relative to the beginning of the active input area; we want an absolute offset
  484.     offset += pWE->tsmAreaStart;
  485.  
  486.     // make sure the offset is within the input area
  487.     if ((offset < pWE->tsmAreaStart) || (offset >= pWE->tsmAreaEnd))
  488.     {
  489.         err = errOffsetInvalid;
  490.         goto cleanup;
  491.     }
  492.  
  493.     // find the position corresponding to the given offset (in long coordinates)
  494.     WEGetPoint(offset, hilite, &thePoint, &lineHeight, hWE);
  495.     thePoint.v += lineHeight;
  496.  
  497.     // make sure offset is within view rectangle
  498.     if ((thePoint.h < pWE->viewRect.left) ||
  499.         (thePoint.h > pWE->viewRect.right ) ||
  500.         (thePoint.v < pWE->viewRect.top) ||
  501.         (thePoint.v > pWE->viewRect.bottom))
  502.     {
  503.         err = errOffsetIsOutsideOfView;
  504.         goto cleanup;
  505.     }
  506.  
  507.     // convert the point to short...
  508.     WELongPointToPoint(&thePoint, &position);
  509.  
  510.     // ...and global coordinates
  511.     GetPort(&savePort);
  512.     SetPort(pWE->port);
  513.     LocalToGlobal(&position);
  514.     SetPort(savePort);
  515.  
  516.     // add keyAEPoint parameter to the reply Apple event
  517.     if ((err = AEPutParamPtr(reply, keyAEPoint, typeQDPoint,
  518.             &position, sizeof(position))) != noErr)
  519.     {
  520.         goto cleanup;
  521.     }
  522.  
  523.     // add keyAETSMTextFont parameter to the reply Apple event
  524.     if ((err = AEPutParamPtr(reply, keyAETSMTextFont, typeShortInteger,
  525.             &pWE->nullStyle.runStyle.tsFont, sizeof(pWE->nullStyle.runStyle.tsFont))) != noErr)
  526.     {
  527.         goto cleanup;
  528.     }
  529.  
  530.     // add keyAETSMTextPointSize parameter to the reply Apple event
  531.     if ((err = AEPutParamPtr(reply, keyAETSMTextPointSize, typeShortInteger,
  532.             &pWE->nullStyle.runStyle.tsSize, sizeof(pWE->nullStyle.runStyle.tsSize))) != noErr)
  533.     {
  534.         goto cleanup;
  535.     }
  536.  
  537.     // add keyAETextLineAscent parameter to the reply Apple event
  538.     if ((err = AEPutParamPtr(reply, keyAETextLineAscent, typeShortInteger,
  539.             &pWE->nullStyle.runAscent, sizeof(pWE->nullStyle.runAscent))) != noErr)
  540.     {
  541.         goto cleanup;
  542.     }
  543.  
  544.     // add keyAETextLineHeight parameter to the reply Apple event
  545.     if ((err = AEPutParamPtr(reply, keyAETextLineHeight, typeShortInteger,
  546.             &pWE->nullStyle.runHeight, sizeof(pWE->nullStyle.runHeight))) != noErr)
  547.     {
  548.         goto cleanup;
  549.     }
  550.  
  551.     // clear result code
  552.     err = noErr;
  553.  
  554. cleanup:
  555.     // unlock the WE record
  556.     if (hWE != nil)
  557.     {
  558.         _WESetHandleLock((Handle) hWE, saveWELock);
  559.     }
  560.  
  561.     // return result code
  562.     return err;
  563. }
  564.  
  565. static pascal OSErr _WEHandleGetText(const AppleEvent *ae, AppleEvent *reply, SInt32 handlerRefCon)
  566. {
  567. #pragma unused(handlerRefCon)
  568.  
  569.     WEHandle hWE = nil;
  570.     WEPtr pWE;
  571.     DescType actualType;
  572.     SInt32 actualSize;
  573.     Boolean saveWELock = false;
  574.     Boolean saveTextLock;
  575.     OSErr err;
  576.  
  577.     // extract WE handle
  578.     if ((err = AEGetParamPtr(ae, keyAETSMDocumentRefcon, typeLongInteger,
  579.             &actualType, &hWE, sizeof(hWE), &actualSize)) != noErr)
  580.     {
  581.         goto cleanup;
  582.     }
  583.  
  584.     // lock the WE record
  585.     saveWELock = _WESetHandleLock((Handle) hWE, true);
  586.     pWE = *hWE;
  587.  
  588.     // return a copy of the selected text in the reply event
  589.     saveTextLock = _WESetHandleLock(pWE->hText, true);
  590.     err = AEPutParamPtr(reply, keyAETheData, typeText,
  591.             *pWE->hText + pWE->selStart, pWE->selEnd - pWE->selStart);
  592.     _WESetHandleLock(pWE->hText, saveTextLock);
  593.     if (err != noErr)
  594.     {
  595.         goto cleanup;
  596.     }
  597.  
  598.     // clear result code
  599.     err = noErr;
  600.  
  601. cleanup:
  602.     // unlock the WE record
  603.     if (hWE != nil)
  604.     {
  605.         _WESetHandleLock((Handle) hWE, saveWELock);
  606.     }
  607.  
  608.     // return result code
  609.     return err;
  610. }
  611.  
  612. #endif    // WASTE_TSM_SUPPORT
  613.  
  614. pascal OSErr WEInstallTSMHandlers(void)
  615. {
  616. #if WASTE_TSM_SUPPORT
  617.     OSErr err;
  618.  
  619.     // the first time we're called, create routine descriptors for our Apple event handlers
  620.     if (_weUpdateActiveInputAreaHandler == nil)
  621.     {
  622.         _weUpdateActiveInputAreaHandler = NewAEEventHandlerProc(_WEHandleUpdateActiveInputArea);
  623.         _wePositionToOffsetHandler = NewAEEventHandlerProc(_WEHandlePositionToOffset);
  624.         _weOffsetToPositionHandler = NewAEEventHandlerProc(_WEHandleOffsetToPosition);
  625.         _weGetTextHandler = NewAEEventHandlerProc(_WEHandleGetText);
  626.     }
  627.  
  628.     // install Apple Event handlers to be used by Text Service components
  629.     if ((err = AEInstallEventHandler(kTextServiceClass, kUpdateActiveInputArea, _weUpdateActiveInputAreaHandler, 0, false)) != noErr)
  630.     {
  631.         goto cleanup;
  632.     }
  633.  
  634.     if ((err = AEInstallEventHandler(kTextServiceClass, kPos2Offset, _wePositionToOffsetHandler, 0, false)) != noErr)
  635.     {
  636.         goto cleanup;
  637.     }
  638.  
  639.     if ((err = AEInstallEventHandler(kTextServiceClass, kOffset2Pos, _weOffsetToPositionHandler, 0, false)) != noErr)
  640.     {
  641.         goto cleanup;
  642.     }
  643.  
  644.     if ((err = AEInstallEventHandler(kTextServiceClass, kGetText, _weGetTextHandler, 0, false)) != noErr)
  645.     {
  646.         goto cleanup;
  647.     }
  648.  
  649.     // clear result code
  650.     err = noErr;
  651.  
  652. cleanup:
  653.     // return result code
  654.     return err;
  655. #else
  656.     return noErr ;
  657. #endif    // WASTE_TSM_SUPPORT
  658. }
  659.  
  660. pascal OSErr WERemoveTSMHandlers(void)
  661. {
  662. #if WASTE_TSM_SUPPORT
  663.     OSErr err;
  664.  
  665.     // return an error code if WEInstallTSMHandlers has never been called
  666.     if (_weUpdateActiveInputAreaHandler == nil)
  667.     {
  668.         return errAEHandlerNotFound;
  669.     }
  670.  
  671.     // remove the handlers
  672.     if ((err = AERemoveEventHandler(kTextServiceClass, kUpdateActiveInputArea, _weUpdateActiveInputAreaHandler, false)) != noErr)
  673.     {
  674.         goto cleanup;
  675.     }
  676.  
  677.     if ((err = AERemoveEventHandler(kTextServiceClass, kPos2Offset, _wePositionToOffsetHandler, false)) != noErr)
  678.     {
  679.         goto cleanup;
  680.     }
  681.  
  682.     if ((err = AERemoveEventHandler(kTextServiceClass, kOffset2Pos, _weOffsetToPositionHandler, false)) != noErr)
  683.     {
  684.         goto cleanup;
  685.     }
  686.  
  687.     if ((err = AERemoveEventHandler(kTextServiceClass, kGetText, _weGetTextHandler, false)) != noErr)
  688.     {
  689.         goto cleanup;
  690.     }
  691.  
  692.     // clear result code
  693.     err = noErr;
  694.  
  695. cleanup:
  696.     // clear result code
  697.     return err;
  698. #else
  699.     return noErr ;
  700. #endif    // WASTE_TSM_SUPPORT
  701. }
  702.  
  703. pascal OSErr WEHandleTSMEvent(const AppleEvent *ae, AppleEvent *reply)
  704. {
  705. #if WASTE_TSM_SUPPORT
  706.     AEEventClass eventClass;
  707.     AEEventID eventID;
  708.     DescType actualType;
  709.     Size actualSize;
  710.     OSErr err;
  711.  
  712.     //    get event class
  713.     if ((err = AEGetAttributePtr(ae, keyEventClassAttr, typeType, &actualType, &eventClass, sizeof(eventClass), &actualSize)) != noErr)
  714.     {
  715.         goto cleanup;
  716.     }
  717.  
  718.     //    make sure the event class is kTextServiceClass
  719.     err = errAEEventNotHandled;
  720.     if (eventClass != kTextServiceClass)
  721.     {
  722.         goto cleanup;
  723.     }
  724.  
  725.     //    get event ID
  726.     if ((err = AEGetAttributePtr(ae, keyEventIDAttr, typeType, &actualType, &eventID, sizeof(eventID), &actualSize)) != noErr)
  727.     {
  728.         goto cleanup;
  729.     }
  730.  
  731.     //    dispatch to appropriate handler
  732.     switch (eventID)
  733.     {
  734.         case kUpdateActiveInputArea:
  735.         {
  736.             err = _WEHandleUpdateActiveInputArea(ae, reply, 0);
  737.             break;
  738.         }
  739.  
  740.         case kPos2Offset:
  741.         {
  742.             err = _WEHandlePositionToOffset(ae, reply, 0);
  743.             break;
  744.         }
  745.  
  746.         case kOffset2Pos:
  747.         {
  748.             err = _WEHandleOffsetToPosition(ae, reply, 0);
  749.             break;
  750.         }
  751.  
  752.         case kGetText:
  753.         {
  754.             err = _WEHandleGetText(ae, reply, 0);
  755.             break;
  756.         }
  757.  
  758.         default:
  759.         {
  760.             break;
  761.         }
  762.     }
  763.  
  764. cleanup:
  765.     return err;
  766. #else
  767.     #pragma unused(ae, reply)
  768.     return errAEEventNotHandled ;
  769. #endif
  770. }
  771.  
  772. pascal void WEStopInlineSession(WEHandle hWE)
  773. {
  774. #if WASTE_TSM_SUPPORT
  775.     WEPtr pWE = *hWE;
  776.  
  777.     // call FixTSMDocument() only if the inline input area is actually "open"
  778.     if ((pWE->tsmAreaStart != kInvalidOffset) && (pWE->tsmReference != nil))
  779.     {
  780.         FixTSMDocument(pWE->tsmReference);
  781.     }
  782. #else
  783. #pragma unused(hWE)
  784. #endif
  785. }
  786.